﻿using MahApps.Metro.Controls;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using WinForm = System.Windows.Forms;

namespace LunarSF.SHomeWorkshop.LunarMarkdownEditor
{
    /// <summary>
    /// LMessageBox.xaml 的交互逻辑
    /// </summary>
    public partial class LMessageBox : MetroWindow
    {
        /// <summary>
        /// [私有构造方法]创建一个自定义的消息框。由于只应该以静态方法的形式弹出自定义消息框，
        /// 所以这里是私有构造方法。
        /// </summary>
        private LMessageBox()
        {
            InitializeComponent();
            Title = Application.Current.MainWindow.Title;
        }

        /// <summary>
        /// 自定义消息框的返回值。
        /// </summary>
        public MessageBoxResult MessageBoxResult { get; set; } = MessageBoxResult.Cancel;

        /// <summary>
        /// 只应该用这几个静态的 Show() 方法来弹出一个消息框。
        /// </summary>
        /// <param name="message">要显示的消息文本。</param>
        /// <returns></returns>
        public static MessageBoxResult Show(string message)
        {
            return Show(message, Application.Current.MainWindow.Title, MessageBoxButton.OK, MessageBoxImage.None);
        }

        /// <summary>
        /// 只应该用这几个静态的 Show() 方法来弹出一个消息框。
        /// </summary>
        /// <param name="message">要显示的消息文本。</param>
        /// <param name="title">消息框的标题文本。</param>
        /// <param name="buttons">消息框上应提供几个按钮。</param>
        /// <param name="image">消息框上应显示什么图标。</param>
        /// <param name="noPromptAgainItemName">下次碰到指定的名称时可能不再提示（取决于用户是否勾选了“不再提示”）。</param>
        /// <param name="helpID">如果提供 helpID，则尝试到教程中找对应链接。通常应是 chm 中的网页名称。</param>
        public static MessageBoxResult Show(string message, string title, MessageBoxButton buttons,
            MessageBoxImage image = MessageBoxImage.None, string noPromptAgainItemName = "", string helpID = null, Window owner = null)
        {
            if (string.IsNullOrEmpty(message)) message = "<未提供消息文本>";

            message = "　　" + message.Trim(new char[] { ' ', '　', '\t', });

            if (string.IsNullOrEmpty(noPromptAgainItemName) == false)
            {
                var mainWindow = Application.Current.MainWindow as MainWindow;
                var configValue = App.ConfigManager.Get(noPromptAgainItemName);
                if (configValue != null)
                {
                    MessageBoxResult defaultResult;
                    if (Enum.TryParse<MessageBoxResult>(configValue, out defaultResult))
                    {
                        return defaultResult;
                    }
                }
            }

            var window = new LMessageBox()
            {
                Owner = owner,
                WindowStartupLocation = (owner == null ? WindowStartupLocation.CenterScreen : WindowStartupLocation.CenterOwner),
                NoPromptAgainItemName = noPromptAgainItemName,
            };

            if (string.IsNullOrWhiteSpace(helpID))
            {
                window.messageBlock.Text = message;
            }
            else
            {
                window.messageBlock.Text = message;
                var span = new Span(new Run("[单击此处显示帮助...]"))
                {
                    Foreground = Brushes.Blue,
                    TextDecorations = TextDecorations.Underline,
                    Tag = helpID,
                };
                span.MouseLeftButtonDown += Span_MouseLeftButtonDown;
                window.messageBlock.Inlines.Add(span);
            }

            #region 确定显示哪些按钮
            switch (buttons)
            {
                case MessageBoxButton.OK:
                    {
                        var btnOK = new LMessageButton() { Content = "确定(_O)", Tag = window, };
                        btnOK.IsDefault = true;
                        btnOK.IsCancel = true;      //此框只用于显示消息。这样按Esc也可以取消了，更顺手些。

                        btnOK.Click += BtnOK_Click;
                        window.panel.Children.Add(btnOK);

                        window.focusedButton = btnOK;
                        window.IsCloseButtonEnabled = false;
                        break;
                    }
                case MessageBoxButton.OKCancel:
                    {
                        var btnOK = new LMessageButton() { Content = "确定(_O)", Tag = window, };
                        btnOK.IsDefault = true;
                        btnOK.Click += BtnOK_Click;

                        var btnCancel = new LMessageButton() { Content = "取消(_C)", Tag = window, };
                        btnCancel.IsCancel = true;
                        btnCancel.Click += BtnCancel_Click;

                        btnOK.NextButton = btnCancel;
                        btnCancel.PreviewButton = btnOK;

                        window.panel.Children.Add(btnOK);
                        window.panel.Children.Add(btnCancel);

                        window.focusedButton = btnOK;
                        window.IsCloseButtonEnabled = true;
                        break;
                    }
                case MessageBoxButton.YesNo:
                    {
                        var btnYes = new LMessageButton() { Content = "是(_Y)", Tag = window, };
                        var btnNo = new LMessageButton() { Content = "否(_N)", Tag = window, };
                        btnYes.IsDefault = true;
                        btnYes.Click += BtnYes_Click;

                        btnNo.IsCancel = true;          //按Esc时，返回的并不是Cancel，而是NO
                        btnNo.Click += BtnNo_Click;

                        btnYes.NextButton = btnNo;
                        btnNo.PreviewButton = btnYes;

                        window.panel.Children.Add(btnYes);
                        window.panel.Children.Add(btnNo);

                        window.focusedButton = btnYes;
                        window.IsCloseButtonEnabled = false;
                        break;
                    }
                //case MessageBoxButton.YesNoCancel:
                default:
                    {
                        var btnYes = new LMessageButton() { Content = "是(_Y)", Tag = window, };
                        btnYes.IsDefault = true;
                        btnYes.Click += BtnYes_Click;

                        var btnNo = new LMessageButton() { Content = "否(_N)", Tag = window, };
                        btnNo.Click += BtnNo_Click;

                        var btnCancel = new LMessageButton() { Content = "取消(_C)", Tag = window, };
                        btnCancel.IsCancel = true;
                        btnCancel.Click += BtnCancel_Click;

                        btnYes.NextButton = btnNo;
                        btnNo.PreviewButton = btnYes;
                        btnNo.NextButton = btnCancel;
                        btnCancel.PreviewButton = btnNo;

                        window.panel.Children.Add(btnYes);
                        window.panel.Children.Add(btnNo);
                        window.panel.Children.Add(btnCancel);

                        window.focusedButton = btnYes;
                        window.IsCloseButtonEnabled = true;
                        break;
                    }
            }
            #endregion

            #region 确定显示哪个图标

            switch (image)
            {
                case MessageBoxImage.Information:
                    {
                        window.img.Source = window.infomation;
                        break;
                    }
                case MessageBoxImage.Warning:
                    {
                        window.img.Source = window.warning;
                        break;
                    }
                case MessageBoxImage.Question:
                    {
                        window.img.Source = window.question;
                        break;
                    }
                case MessageBoxImage.Error:
                    {
                        window.img.Source = window.error;
                        break;
                    }
                default:
                    {
                        window.img.Visibility = Visibility.Collapsed;
                        break;
                    }
            }

            #endregion

            window.ShowDialog();
            return window.MessageBoxResult;
        }

        private static void Span_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            var bookFullName = Globals.InstalledPath + "Lunar_Markdown_Editor_教程.chm";
            if (File.Exists(bookFullName))
            {
                WinForm.Help.ShowHelp(null, bookFullName,
                        WinForm.HelpNavigator.Topic, (sender as Span).Tag as string);
            }
        }

        #region 消息框使用的几种图标
        private ImageSource warning = new BitmapImage(new Uri("pack://application:,,,/LunarMarkdownEditor;component/Images/MessageBoxIcons/warning.png"));
        private ImageSource error = new BitmapImage(new Uri("pack://application:,,,/LunarMarkdownEditor;component/Images/MessageBoxIcons/error.png"));
        private ImageSource question = new BitmapImage(new Uri("pack://application:,,,/LunarMarkdownEditor;component/Images/MessageBoxIcons/question.png"));
        private ImageSource infomation = new BitmapImage(new Uri("pack://application:,,,/LunarMarkdownEditor;component/Images/MessageBoxIcons/infomation.png"));
        #endregion

        private string noPromptAgainItemName = "";
        /// <summary>
        /// 不再提示的项的名称。此名称将会被写入程序的XmlConfig文件中。
        /// </summary>
        public string NoPromptAgainItemName
        {
            get { return this.noPromptAgainItemName; }
            set { this.noPromptAgainItemName = value; }
        }

        /// <summary>
        /// 消息框载入时的默认聚焦的按钮。
        /// </summary>
        private LMessageButton focusedButton = null;

        /// <summary>
        /// 将指定不再提示项的值写入配置文件中。
        /// </summary>
        private void WriteNoPromptAgainItemValue()
        {
            if (ckxNoPromptAgain.IsChecked != true) return;
            if (string.IsNullOrEmpty(this.NoPromptAgainItemName)) return;
            if (Globals.MainWindow == null || App.ConfigManager == null) return;

            App.ConfigManager.Set(NoPromptAgainItemName, this.MessageBoxResult.ToString());
        }

        /// <summary>
        /// OK 按钮被按下，返回 MessageBoxResult.OK。
        /// </summary>
        private static void BtnOK_Click(object sender, RoutedEventArgs e)
        {
            ((sender as Button).Tag as LMessageBox).MessageBoxResult = MessageBoxResult.OK;
            ((sender as Button).Tag as LMessageBox).Close();
        }

        /// <summary>
        /// Yes 按钮被按下，返回 MessageBoxResult.Yes。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void BtnYes_Click(object sender, RoutedEventArgs e)
        {
            ((sender as Button).Tag as LMessageBox).MessageBoxResult = MessageBoxResult.Yes;
            ((sender as Button).Tag as LMessageBox).Close();
        }

        /// <summary>
        /// Cancel 按钮被按下，返回 MessageBoxResult.Cancel。
        /// </summary>
        private static void BtnCancel_Click(object sender, RoutedEventArgs e)
        {
            ((sender as Button).Tag as LMessageBox).MessageBoxResult = MessageBoxResult.Cancel;
            ((sender as Button).Tag as LMessageBox).Close();
        }

        /// <summary>
        /// No 按钮被按下，返回 MessageBoxResult.No。
        /// </summary>
        private static void BtnNo_Click(object sender, RoutedEventArgs e)
        {
            ((sender as Button).Tag as LMessageBox).MessageBoxResult = MessageBoxResult.No;
            ((sender as Button).Tag as LMessageBox).Close();
        }

        /// <summary>
        /// 处理快捷键。
        /// </summary>
        private void MetroWindow_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            switch (e.Key)
            {
                case Key.Left:
                    {
                        if (focusedButton == null) return;

                        var previewButton = focusedButton.PreviewButton;
                        if (previewButton == null) return;

                        e.Handled = true;
                        previewButton.Focus();
                        focusedButton = previewButton;
                        break;
                    }
                case Key.Right:
                    {
                        if (focusedButton == null) return;

                        var nextButton = focusedButton.NextButton;
                        if (nextButton == null) return;

                        e.Handled = true;
                        nextButton.Focus();
                        focusedButton = nextButton;
                        break;
                    }
            }
        }

        private void MetroWindow_PreviewKeyUp(object sender, KeyEventArgs e)
        {
            e.Handled = true;
        }

        private void MetroWindow_Closed(object sender, EventArgs e)
        {
            WriteNoPromptAgainItemValue();
        }

        private void MetroWindow_Loaded(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(this.NoPromptAgainItemName) == false)
            {
                ckxNoPromptAgain.Visibility = Visibility.Visible;//否则隐藏。
            }
        }
    }

}
